﻿using IBaseRepository;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json.Linq;
using SqlSugar;
using SqlSugarAndEntity.Entity;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using Services.Base;
using Services.Org;
using Common.NpoiHelper;
using Common.ExpressionHelper;
using Common.PasswordHelper;
using Common.ReflectionHelper;
using Common.CommonModel;
using AutoRegistDependency.Attributes;
using Core.JwtService;
using Newtonsoft.Json;
using System.Threading.Tasks;
using System.Threading;
using Repository.Base;
using SqlSugarAndEntity.DataTransferObject.Test;
using Core.Proxy.Enums;
using Core.Proxy.Attributes.InterceptorAttributes;
using Serilog;

namespace Services.User
{
    [Component]
    public class UserService :BaseService<sys_userinfo>, IUserService
    {
        private IUserRepository userRepository;
        [Autowired]
        private IBaseRepository<sys_usermaporg> userMapOrgRepository;
        private IConfiguration configuration;
        [Autowired]
        private IOrgService orgService { get; set; }
        [Value("AESKey")]
        private string pwdKey { get; set; }
        public UserService(IUserRepository userRepository,IConfiguration configuration) :base(userRepository)
        {
            this.userRepository = userRepository;
            //this.orgService = orgService;
            this.configuration = configuration;
            //this.userMapOrgRepository = userMapOrgRepository;
        }
        [Transaction]
        public ResponseModel CreateUserInfo(sys_userinfo user, List<sys_usermaporg> map)
        {
            var result = new ResponseModel();
            if (userRepository.GetUserInfo((a, b, c) => a.UserAccount == user.UserAccount, 1, 10).Items.FirstOrDefault() != null)
            {
                result.code = ResponseTypeEnum.AccountAlreadyExists;
                result.message = ResponseTypeEnum.AccountAlreadyExists;
                return result;
            }
            userRepository.Insert(user);

            //userMapOrgRepository.Insert(map);
            result.code= ResponseTypeEnum.GetInfoSucess;
            result.message = ResponseTypeEnum.GetInfoSucess;
            return result;
        }

        public ResponseModel DeleteUserInfo(Expression<Func<sys_userinfo, bool>> UserExp, Expression<Func<sys_usermaporg, bool>> MapExp)
        {
            return CreateResponseModel(userRepository.DeleteUserinfo, UserExp, MapExp);
        }

        public string ExportUserinfo(string Name, string UserAccount, string UserPhone, string IdNumber, string OrgName)
        {
            Expression<Func<sys_userinfo, sys_usermaporg, sys_orginfo, bool>> OrginExp = null;
            Expression<Func<sys_userinfo, sys_usermaporg, sys_orginfo, bool>> WhereExp = OrginExp
                .AndIF(!string.IsNullOrEmpty(Name), (a, b, c) => a.UserName.Contains(Name))
                .AndIF(!string.IsNullOrEmpty(UserAccount), (a, b, c) => a.UserPhone.Contains(UserPhone))
                .AndIF(!string.IsNullOrEmpty(IdNumber), (a, b, c) => a.IdNumber.Contains(IdNumber))
                .AndIF(!string.IsNullOrEmpty(OrgName), (a, b, c) => c.OrgName.Contains(OrgName));
            var list = userRepository.GetUserInfo(WhereExp,1,5000);
            string FilePath = NpoiHelper.ExportExcelToFilePath(list.Items);
            return FilePath;
        }
        public ResponseModel GetUserInfo(string Name, string UserAccount, string UserPhone, string IdNumber, string OrgName, int page, int limit)
        {
            ResponseModel res = new ResponseModel();
            Expression<Func<sys_userinfo, sys_usermaporg, sys_orginfo, bool>> OrginExp = null;
            Expression<Func<sys_userinfo, sys_usermaporg, sys_orginfo, bool>> WhereExp = OrginExp
                .AndIF(!string.IsNullOrEmpty(Name), (a, b, c) => a.UserName.Contains(Name))
                .AndIF(!string.IsNullOrEmpty(UserAccount), (a, b, c) => a.UserPhone.Contains(UserPhone))
                .AndIF(!string.IsNullOrEmpty(IdNumber), (a, b, c) => a.IdNumber.Contains(IdNumber))
                .AndIF(!string.IsNullOrEmpty(OrgName), (a, b, c) => c.OrgName.Contains(OrgName));
            var list = userRepository.GetUserInfo(WhereExp, page, limit);
            list.Items.ForEach(t =>
            {
                //把用户密码解密
                t.UserPassWord = AESHelper.AesDecrypt(t.UserPassWord, pwdKey);
            });
            res.model = list;
            return res; 
            //return CreateResponseModelByPage(userRepository.GetUserInfo, WhereExp, page, limit, ref total);
        }

        public ResponseModel ImportUserinfo(Stream s)
        {
            throw new NotImplementedException();
        }
        public ResponseModel Login(string account, string password)
        {
            ResponseModel res = new ResponseModel();
            var userlist = userRepository.GetUserInfo((a, b, c) => a.UserAccount == account,1,10);
            if (userlist.Items.Count == 0)
            {
                res.code = ResponseTypeEnum.AccountNotExists;
                res.message = ResponseTypeEnum.AccountNotExists;
            }
            else
            {
                string AESPwd = AESHelper.AesEncrypt(password, pwdKey);
                var userinfo = userlist.Items.Where(t => t.UserPassWord == AESPwd).FirstOrDefault();
                if (userinfo != null)
                {
                    res.code = ResponseTypeEnum.LoginSucess;
                    res.message = ResponseTypeEnum.LoginSucess;
                    userinfo.UserPassWord = null;
                    var payload = new Dictionary<string, string>()
                    {
                        {"userinfo",JsonConvert.SerializeObject(userinfo) }
                    };
                    //生成请求token 测试用1分钟
                    string RequestToken = JwtExtensions.CreateToken(payload);
                    //生成RefreshToken
                    string RefreshToken = JwtExtensions.CreateToken(payload, false);
                    res.model = new { RequestToken = RequestToken, RefreshToken = RefreshToken };
                }
                else
                {
                    res.code = ResponseTypeEnum.PwdError;
                    res.message = ReflectionConvertHelper.GetEnumDescription(ResponseTypeEnum.PwdError);
                }
            }
            return res;

        }

        public ResponseModel RefreshToken(JObject value)
        {
            ResponseModel res = new ResponseModel();
            string RefreshToken = value.Value<string>("refreshToken");
            if (RefreshToken == null)
            {
                res.code = ResponseTypeEnum.NoToken;
                res.message = ResponseTypeEnum.NoToken;
                return res;
            }
            //验证token有效性
            bool flag= JwtExtensions.ValidateToken(RefreshToken, false);
            //验证失败
            if (!flag)
            {
                res.code = ResponseTypeEnum.IllegalToken;
            }
            else
            {
                //验证成功
                //jwt先拆成3段
                //jwt前两段重新用requestkey加密
                //string RequestToken = CreateEncodedSignature(RequestKey, JwtData.baseInfo, JwtData.info);
                res.code = ResponseTypeEnum.TokenSucess;
                res.message = ResponseTypeEnum.TokenSucess;
                var userinfo= JwtExtensions.GetData<sys_userinfo>(RefreshToken);
                decimal userid = userinfo.ID;
                var user = userRepository.GetUserInfo((a, b, c) => a.ID == userid, 1, 10).Items.FirstOrDefault();
                userinfo.UserPassWord = null;
                var payload = new Dictionary<string, string>()
                {
                    {"userinfo",JsonConvert.SerializeObject(userinfo) }
                };
                res.model = JwtExtensions.CreateToken(payload, false);

                //res.model = CreateNewToken(RequestKey, JwtData, 10);
            }
            return res;
        }
        [CacheLock(constKey: "UpdateUserInfo", maxLockMillisecond: 5000, retryInterval: 1000,dynamicParamKeys: "user.ID")]

        public ResponseModel UpdateUserInfo(sys_userinfo user, List<sys_usermaporg> map)
        {
            return CreateResponseModel(userRepository.UpdateUserInfo, user, map);
        }
        public ResponseModel GetRoleAuthorized(decimal roleId, int page, int limit)
        {
            return CreateResponseModel(userRepository.GetRoleAuthorized, roleId, page, limit);
        }

        public ResponseModel GetRoleNotAuthorized(decimal roleId, int page, int limit)
        {
            return CreateResponseModel(userRepository.GetRoleNotAuthorized, roleId, page, limit);
        }

        public ResponseModel UpdateUserPwd(decimal UserId,string OldPwd,string NewPwd)
        {
            ResponseModel res = new ResponseModel();
            var user = userRepository.GetInfo(t => t.ID == UserId).FirstOrDefault();
            if (user == null)
            {
                throw new Exception("用户不存在！");
            }
            string PwdKey = configuration.GetSection("AESKey").Value;
            string AESPwd = AESHelper.AesEncrypt(OldPwd, PwdKey);
            if (user.UserPassWord != AESPwd)
            {
                res.code = ResponseTypeEnum.PwdError;
                return res;
            }
            else
            {
                string NewAes = AESHelper.AesEncrypt(NewPwd, PwdKey);
                return CreateResponseModel<Expression<Func<sys_userinfo, sys_userinfo>>,Expression<Func<sys_userinfo, bool>>,bool> (userRepository.Update, t => new sys_userinfo() { UserPassWord = NewAes }, t => t.ID == UserId);
            }
        }
        [ReturnValueCache(expireMillisecond:300,constKey: "TestAsync","num")]
        public async Task<int> TestAsync(int num)
        {
            Console.WriteLine($"TestAsync:{Thread.CurrentThread.ManagedThreadId}");
            var res= await Task.Run(() =>
            {
                Console.WriteLine($"Task:{Thread.CurrentThread.ManagedThreadId}");
                return 1;
                
            });
            Console.WriteLine($"TestAsync:{Thread.CurrentThread.ManagedThreadId}");
            return res;
        }
        [ReturnValueCache(expireMillisecond: 300, constKey: "TestClassAsync")]
        [Transaction]
        public async Task<sys_userinfo> TestClassAsync()
        {
            return await Task.Run(() =>
            {
                return new sys_userinfo()
                {
                    ID = 1,
                    UserName = "TestClassAsync"
                };
            });
        }
        [ReturnValueCache(expireMillisecond: 300, constKey: "Test")]
        public int Test()
        {
            return 2;
        }
        [ReturnValueCache(expireMillisecond: 300, constKey: "TestClass")]
        public sys_userinfo TestClass()
        {
            return new sys_userinfo()
            {
                ID = 1,
                UserName = "TestClass"
            };
        }
        [CacheLock(constKey: "TestProxy",cacheKeyPrefix:CacheKeyPrefix.ClassNameAndMethodName,dynamicParamKeys: "testProxy.testProxyChildren")]
        public int TestProxy(TestProxy testProxy)
        {
            return 1;
        }
    }
}
